home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / tcop / pquery.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  14.0 KB  |  544 lines

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *    pquery.c
  4.  *    
  5.  *   DESCRIPTION
  6.  *    POSTGRES process query command code
  7.  *
  8.  *   INTERFACE ROUTINES
  9.  *    ProcessQuery
  10.  *    ParallelProcessQueries
  11.  *
  12.  *   NOTES
  13.  *
  14.  *   IDENTIFICATION
  15.  *    $Header: /private/postgres/src/tcop/RCS/pquery.c,v 1.54 1992/08/18 18:27:16 mer Exp $
  16.  * ----------------------------------------------------------------
  17.  */
  18.  
  19. #include "tmp/postgres.h"
  20.  
  21. RcsId("$Header: /private/postgres/src/tcop/RCS/pquery.c,v 1.54 1992/08/18 18:27:16 mer Exp $");
  22.  
  23. /* ----------------
  24.  *    FILE INCLUDE ORDER GUIDELINES
  25.  *
  26.  *    1) tcopdebug.h
  27.  *    2) various support files ("everything else")
  28.  *    3) node files
  29.  *    4) catalog/ files
  30.  *    5) execdefs.h and execmisc.h, if necessary.
  31.  *    6) extern files come last.
  32.  * ----------------
  33.  */
  34. #include "tcop/tcopdebug.h"
  35.  
  36. #include "parser/parse.h"
  37. #include "parser/parsetree.h"
  38. #include "utils/log.h"
  39. #include "utils/mcxt.h"
  40. #include "tmp/miscadmin.h"
  41. #include "tmp/portal.h"
  42.  
  43. #include "nodes/pg_lisp.h"
  44. #include "nodes/primnodes.h"
  45. #include "nodes/primnodes.a.h"
  46. #include "nodes/plannodes.h"
  47. #include "nodes/plannodes.a.h"
  48. #include "nodes/execnodes.h"
  49. #include "nodes/execnodes.a.h"
  50. #include "nodes/mnodes.h"
  51.  
  52. #include "tcop/dest.h"
  53. #include "commands/command.h"
  54.  
  55. #include "executor/execdefs.h"
  56. #include "executor/execmisc.h"
  57. #include "executor/x_execmain.h"
  58. #include "tcop/pfrag.h"
  59. #include "tcop/pquery.h"
  60. #include "lib/lisplist.h"
  61.  
  62. /* ----------------------------------------------------------------
  63.  *    MakeQueryDesc is a utility used by ProcessQuery and
  64.  *    the rule manager to build a query descriptor..
  65.  * ----------------------------------------------------------------
  66.  */
  67. List
  68. MakeQueryDesc(operation, parsetree, plantree, state, feature,
  69.           arglist, typelist, nargs, dest)
  70.     List      operation;
  71.     List      parsetree;
  72.     Plan      plantree;
  73.     List      state;
  74.     List      feature;
  75.     List    arglist;
  76.     List    typelist;
  77.     LispValue    nargs;
  78.     CommandDest dest;
  79. {
  80.     return
  81.     MakeList(operation,          /* operation */
  82.          parsetree,         /* parse tree */
  83.          plantree,         /* plan */
  84.          state,         /* state */
  85.          feature,         /* feature */
  86.          lispInteger((int)dest), /* output dest */
  87.          arglist,        /* arg list to query */
  88.          typelist,        /* types of args */
  89.          nargs,            /* number of arguments */
  90.          -1);
  91.  
  92. }
  93.  
  94. /* ----------------------------------------------------------------
  95.  *    CreateQueryDesc is a simpler interface to MakeQueryDesc
  96.  * ----------------------------------------------------------------
  97.  */
  98. List
  99. CreateQueryDesc(parsetree, plantree, argv, typev, nargs, dest)
  100.     List     parsetree;
  101.     Plan     plantree;
  102.     char    **argv;
  103.     ObjectId    *typev;
  104.     int        nargs;
  105.     CommandDest dest;
  106. {
  107.     List arglist;
  108.     List typelist;
  109.     int i;
  110.  
  111.     arglist = typelist = LispNil;
  112.  
  113.     for (i = 0; i < nargs; i++) {
  114.     /*
  115.      * XXX argv is really a vector of Datum.  Using lispInteger works
  116.      *     but semantically it is bs.   mer 30 Jun 1992
  117.      */
  118.     arglist = nappend1(arglist, lispInteger(*argv++));
  119.     typelist = nappend1(typelist, lispInteger(*typev++));
  120.     }
  121.  
  122.     return MakeQueryDesc(CAR(CDR(CAR(parsetree))),     /* operation */
  123.              parsetree,            /* parse tree */
  124.              plantree,            /* plan */
  125.              LispNil,            /* state */
  126.              LispNil,            /* feature */
  127.              arglist,            /* args to query */
  128.              typelist,            /* arg types */
  129.              lispInteger(nargs),        /* # of args */
  130.              dest);                /* output dest */
  131. }
  132.  
  133. /* ----------------------------------------------------------------
  134.  *    CreateExecutorState
  135.  *
  136.  *    Note: this may someday take parameters -cim 9/18/89
  137.  * ----------------------------------------------------------------
  138.  */
  139. EState
  140. CreateExecutorState()
  141. {
  142.     EState        state;
  143.     TupleCount        tuplecount;
  144.     extern int        NBuffers;
  145.  
  146.     /* ----------------
  147.      *    create a new executor state
  148.      * ----------------
  149.      */
  150.     state = (EState) RMakeEState();
  151.                
  152.     /* ----------------
  153.      *    initialize the Executor State structure
  154.      * ----------------
  155.      */
  156.     set_es_direction(state, EXEC_FRWD);
  157.     set_es_time(state, 0);
  158.     set_es_owner(state, 0);
  159.     set_es_locks(state, LispNil);
  160.     set_es_subplan_info(state, LispNil);
  161.     set_es_error_message(state, NULL);
  162.     set_es_range_table(state, LispNil);
  163.     
  164.     set_es_qualification_tuple(state, NULL);
  165.     set_es_qualification_tuple_id(state, NULL);
  166.     set_es_qualification_tuple_buffer(state, InvalidBuffer);
  167.     set_es_raw_qualification_tuple(state, NULL);
  168.     
  169.     set_es_relation_relation_descriptor(state, NULL);
  170.     set_es_into_relation_descriptor(state, NULL);
  171.     set_es_result_relation_info(state, NULL);
  172.     set_es_result_relation_info_list(state, NULL);
  173.  
  174.     tuplecount = MakeTupleCount(0,     /* retrieved */
  175.                 0,     /* appended */
  176.                 0,     /* deleted */
  177.                 0,     /* replaced */
  178.                 0,     /* inserted */
  179.                 0);     /* processed */
  180.     
  181.     set_es_tuplecount(state, tuplecount);
  182.     
  183.     set_es_param_list_info(state, NULL);
  184.     set_es_prs2_info(state, NULL);
  185.     set_es_explain_relation(state, NULL);
  186.     
  187.     set_es_BaseId(state, 0);
  188.     set_es_tupleTable(state, NULL);
  189.  
  190.     set_es_junkFilter(state, NULL);
  191.     set_es_junkFilter_list(state, NULL);
  192.     set_es_result_rel_scanstate(state, NULL);
  193.     set_es_result_rel_ruleinfo(state, NULL);
  194.  
  195.     set_es_whichplan(state, -1);
  196.     set_es_refcount(state, (int*)palloc(NBuffers * sizeof(int)));
  197.     /* ----------------
  198.      *    return the executor state structure
  199.      * ----------------
  200.      */
  201.     return state;
  202. }
  203.  
  204. /* ----------------------------------------------------------------
  205.  *    CreateOperationTag
  206.  *
  207.  *    utility to get a string representation of the
  208.  *    query operation.
  209.  * ----------------------------------------------------------------
  210.  */
  211. String
  212. CreateOperationTag(operationType)
  213.     int    operationType;
  214. {
  215.     String tag;
  216.     
  217.     switch (operationType) {
  218.     case RETRIEVE:
  219.     tag = "RETRIEVE";
  220.     break;
  221.     case APPEND:
  222.     tag = "APPEND";
  223.     break;
  224.     case DELETE:
  225.     tag = "DELETE";
  226.     break;
  227.     case EXECUTE:
  228.     tag = "EXECUTE";
  229.     break;
  230.     case REPLACE:
  231.     tag = "REPLACE";
  232.     break;
  233.     default:
  234.     elog(DEBUG, "CreateOperationTag: unknown operation type %d", 
  235.          operationType);
  236.     tag = NULL;
  237.     break;
  238.     }
  239.     
  240.     return tag;
  241. }
  242.  
  243. /* ----------------
  244.  *    ProcessPortal
  245.  * ----------------
  246.  */
  247.  
  248. void
  249. ProcessPortal(portalName, portalType, parseTree, plan, state, attinfo, dest)
  250.     String     portalName;
  251.     int         portalType;    /* XXX unused */
  252.     List    parseTree;
  253.     Plan    plan;
  254.     EState    state;
  255.     List    attinfo;
  256.     CommandDest dest;
  257. {
  258.     Portal        portal;
  259.     MemoryContext     portalContext;
  260.  
  261.     /* ----------------
  262.      *   convert the current blank portal into the user-specified
  263.      *   portal and initialize the state and query descriptor.
  264.      * ----------------
  265.      */
  266.     
  267.     if (PortalNameIsSpecial(portalName))
  268.     elog(WARN,
  269.          "The portal name %s is reserved for internal use",
  270.          portalName);
  271.  
  272.     portal = BlankPortalAssignName(portalName);
  273.  
  274.     PortalSetQuery(portal,
  275.            CreateQueryDesc(parseTree, plan, (char *) NULL,
  276.                    (ObjectId *) NULL, 0, dest),
  277.            state,
  278.            PortalCleanup);
  279.  
  280.     /* ----------------
  281.      *    now create a new blank portal and switch to it. 
  282.      *    Otherwise, the new named portal will be cleaned.
  283.      *
  284.      *  Note: portals will only be supported within a BEGIN...END
  285.      *  block in the near future.  Later, someone will fix it to
  286.      *  do what is possible across transaction boundries. -hirohama
  287.      * ----------------
  288.      */
  289.     portalContext = (MemoryContext)
  290.     PortalGetHeapMemory(GetPortalByName(NULL));
  291.     
  292.     MemoryContextSwitchTo(portalContext);
  293.     
  294.     StartPortalAllocMode(DefaultAllocMode, 0);
  295. }
  296.  
  297.  
  298. /* ----------------------------------------------------------------
  299.  *    ProcessQueryDesc
  300.  *
  301.  *    Read the comments for ProcessQuery() below...
  302.  * ----------------------------------------------------------------
  303.  */
  304. void
  305. ProcessQueryDesc(queryDesc)
  306.     List     queryDesc;
  307. {
  308.     List     parseTree;
  309.     Plan     plan;
  310.     int        operation;
  311.     String    tag;
  312.     EState     state;
  313.     List     feature_start;
  314.     List     feature_run;
  315.     List     feature_end;
  316.     List     attinfo;
  317.     
  318.     List    parseRoot;
  319.     bool    isRetrieveIntoPortal;
  320.     bool    isRetrieveIntoRelation;
  321.     bool    isRetrieveIntoTemp;
  322.     String    intoName;
  323.     int         intoType = 0;
  324.     CommandDest dest;
  325.  
  326.     /* ----------------
  327.      *    get info from the query desc
  328.      * ----------------
  329.      */
  330.     parseTree = QdGetParseTree(queryDesc);
  331.     plan =    QdGetPlan(queryDesc);
  332.     
  333.     operation = CAtom(GetOperation(queryDesc));
  334.     tag =     CreateOperationTag(operation);
  335.     dest =     QdGetDest(queryDesc);
  336.     
  337.     /* ----------------
  338.      *    initialize portal/into relation status
  339.      * ----------------
  340.      */
  341.     isRetrieveIntoPortal =   false;
  342.     isRetrieveIntoRelation = false;
  343.     isRetrieveIntoTemp =     false;
  344.     
  345.     if (operation == RETRIEVE) {
  346.     List    resultDesc;
  347.     int    resultDest;
  348.  
  349.     parseRoot = parse_tree_root(parseTree);
  350.     resultDesc = root_result_relation(parseRoot);
  351.     if (!lispNullp(resultDesc)) {
  352.         resultDest = CAtom(CAR(resultDesc));
  353.         if (resultDest == PORTAL) {
  354.         isRetrieveIntoPortal = true;
  355.         intoName = CString(CADR(resultDesc));
  356.         } else if (resultDest == IPORTAL) {
  357.         isRetrieveIntoPortal = true;
  358.         intoName = CString(CADR(resultDesc));
  359.         /*
  360.          * For internal format portals, we change Remote
  361.          * (externalized form) to RemoteInternal (internalized
  362.          * form)
  363.          */
  364.         Assert(dest == Remote);
  365.         QdSetDest(queryDesc,RemoteInternal);
  366.             dest =     QdGetDest(queryDesc);
  367.         Assert(dest == RemoteInternal);
  368.         } else if (resultDest == INTO || resultDest == INTOTEMP) {
  369.         isRetrieveIntoRelation = true;
  370.         if (resultDest == INTOTEMP)
  371.            isRetrieveIntoTemp = true;
  372.         }
  373.     }
  374.     }
  375.  
  376.     /* ----------------
  377.      *    when performing a retrieve into, we override the normal
  378.      *  communication destination during the processing of the
  379.      *  the query.  This only affects the tuple-output function
  380.      *  - the correct destination will still see BeginCommand()
  381.      *  and EndCommand() messages.
  382.      * ----------------
  383.      */
  384.     if (isRetrieveIntoRelation)
  385.         QdSetDest(queryDesc, (int) None);
  386.  
  387.     /* ----------------
  388.      *    create a default executor state.. 
  389.      * ----------------
  390.      */
  391.     state = CreateExecutorState();
  392.  
  393.     /* ----------------
  394.      *    create the executor "features"
  395.      * ----------------
  396.      */
  397.     feature_start = MakeList(lispInteger(EXEC_START), -1);
  398.     feature_run =   MakeList(lispInteger(EXEC_RUN), -1);
  399.     feature_end =   MakeList(lispInteger(EXEC_END), -1);
  400.     
  401.     /* ----------------
  402.      *    call ExecMain with EXEC_START to
  403.      *  prepare the plan for execution
  404.      * ----------------
  405.      */
  406.     attinfo = ExecMain(queryDesc, state, feature_start);
  407.     
  408.     /* ----------------
  409.      *   report the query's result type information
  410.      *   back to the front end or to whatever destination
  411.      *   we're dealing with.
  412.      * ----------------
  413.      */
  414.     BeginCommand(NULL,
  415.          operation,
  416.          attinfo,
  417.          isRetrieveIntoRelation,
  418.          isRetrieveIntoPortal,
  419.          tag,
  420.          dest);
  421.  
  422.     /* ----------------
  423.      *  Named portals do not do a "fetch all" initially, so now
  424.      *  we return since ExecMain has been called with EXEC_START
  425.      *  to initialize the query plan.  
  426.      *
  427.      *  Note: ProcessPortal transforms the current "blank" portal
  428.      *        into a named portal and creates a new blank portal so
  429.      *          everything we allocated in the current "blank" memory
  430.      *          context will be preserved across queries.  -cim 2/22/91
  431.      * ----------------
  432.      */
  433.     if (isRetrieveIntoPortal) {
  434.     extern MemoryContext PortalExecutorHeapMemory;
  435.     PortalExecutorHeapMemory = NULL;
  436.     
  437.     ProcessPortal(intoName,
  438.               intoType,
  439.               parseTree,
  440.               plan,
  441.               state,
  442.               attinfo,
  443.               dest);
  444.  
  445.     EndCommand(tag, dest);
  446.     return;
  447.     }
  448.     
  449.     /* ----------------
  450.      *   Now we get to the important call to ExecMain() where we
  451.      *   actually run the plan..
  452.      * ----------------
  453.      */
  454.     (void) ExecMain(queryDesc, state, feature_run);
  455.  
  456.     /* ----------------
  457.      *   final call to ExecMain.. we close down all the scans
  458.      *   and free allocated resources...
  459.      * ----------------
  460.      */
  461.     (void) ExecMain(queryDesc, state, feature_end);
  462.  
  463. #ifdef EXEC_TUPLECOUNT        
  464.     /* ----------------
  465.      *    print tuple counts.. note this is only a temporary
  466.      *  place for this because statistics are stored in the
  467.      *  execution state.. it should be moved someplace else
  468.      *  someday -cim 10/16/89
  469.      * ----------------
  470.      */
  471.     DisplayTupleCount(state);
  472. #endif EXEC_TUPLECOUNT        
  473.  
  474.     /* ----------------
  475.      *  Notify the destination of end of processing.
  476.      * ----------------
  477.      */
  478.     EndCommand(tag, dest);
  479. }
  480.  
  481. /* ----------------------------------------------------------------
  482.  *    ProcessQuery
  483.  *
  484.  *    Execute a plan, the non-parallel version
  485.  * ----------------------------------------------------------------
  486.  */
  487.  
  488. void
  489. ProcessQuery(parsertree, plan, argv, typev, nargs, dest)
  490.     List        parsertree;
  491.     Plan        plan;
  492.     char    *argv;
  493.     ObjectId    *typev;
  494.     int        nargs;
  495.     CommandDest dest;
  496. {
  497.     List queryDesc;
  498.     extern int    testFlag;
  499.  
  500.     if (testFlag) dest = None;
  501.     queryDesc = CreateQueryDesc(parsertree, plan, argv, typev, nargs, dest);
  502.     ProcessQueryDesc(queryDesc);
  503. }
  504.  
  505. /* ----------------------------------------------------
  506.  *    ParallelProcessQuery
  507.  *
  508.  *    The parallel version of ProcessQuery().  Also tries to
  509.  *    explore inter-query parallelism.
  510.  * ----------------------------------------------------
  511.  */
  512.  
  513. void
  514. ParallelProcessQueries(parsetree_list, plan_list, dest)
  515.     List     parsetree_list;
  516.     List     plan_list;
  517.     CommandDest dest;
  518. {
  519.     Fragment    rootFragment;
  520.     List    fragmentList;
  521.     LispValue    x, plist;
  522.     List    parsetree;
  523.     Plan    plan;
  524.     
  525.     /*
  526.      *  haven't tried to integrate the argv, typev, nargs changes to
  527.      *  ProcessQuery() into this code, because i don't understand this
  528.      *  code.  need to get this right before we run this routine.
  529.      */
  530.     elog(WARN, "hey wei, you need to talk to mao.");
  531.  
  532.     plist = plan_list;
  533.     fragmentList = LispNil;
  534.     foreach (x, parsetree_list) {
  535.     parsetree = CAR(x);
  536.     plan = (Plan)CAR(plist);
  537.     plist = CDR(plist);
  538.     rootFragment = InitialPlanFragments(parsetree, plan);
  539.     fragmentList = nappend1(fragmentList, (LispValue)rootFragment);
  540.       }
  541.  
  542.     OptimizeAndExecuteFragments(fragmentList, dest);
  543. }
  544.